v-bind
和v-on
在沒有props
的情況下一樣可以得到父層的資料。
<div id="app">
<my-component :class="className" @click="greeting"></my-component>
</div>
<!--渲染後<div class="card block">Vue</div>--->
const app = Vue.createApp({
data() {
return {
className: 'block'
}
},
methods: {
greeting() {
alert('Hi')
}
}
});
app.component('my-component', {
template: `
<div class="card"></div>
`,
})
app.mount('#app');
補充:
v-bind="$sttrs"
在多個節點的情況下,Vue找不到DOM就會出現錯誤,加上v-bind="$sttrs"
可以告訴他DOM在哪
app.component('my-component', {
template: `
<header>...</header>
<body v-bind="$sttrs">...</body>
<footer>...</footer>
`
})
inheritAttrs: false
不想要子元素繼承資料可以加這個。
app.component('my-component', {
inheritAttrs: false,
template: `.....`
})
子元件中包子元件,常看到的樣子就是像樹狀圖那樣的結構,如: 側選單含有次選單。
遞迴一定要有name
屬性,不然元件就不能呼叫,呼叫時最好也有:key
做為唯一的標籤。
<div id="app">
<menu-component :title="menuData.name" :child="menuData.childNodes"></menu-component>
</div>
const menuData = {
name: 'uniqlo',
childNodes: [{
name: 'women',
url: null,
childNodes: [{
name: 'top',
url: 'https://www.uniqlo.com/tw/special/outerlineup/women/'
},
{
name: 'inner',
url: 'https://www.uniqlo.com/tw/store/feature/women/inner/wireless-bra/'
}]
},
{
name: 'men',
url: null,
childNodes: [{
name: 'top',
url: 'https://www.uniqlo.com/tw/special/topscollection/men/'
}, {
name: 'bottom',
url: 'https://www.uniqlo.com/tw/special/bottomscollection/men/'
},
{
name: 'shirts',
url: 'https://www.uniqlo.com/tw/store/feature/men/tops/dress-shirts-long-and-short/'
}]
}, {
name: 'child',
url: null,
}
]
}
const app = Vue.createApp({
data() {
return {
menuData
}
}
});
app.component('menu-component', {
name: `menu-component`,
props: {
title: String,
url: String,
child: {
type: Array,
default: []
}
},
data() {
return {
isOpen: false
}
},
template: `
<ul>
<li>
<template v-if="child.length > 0">
<h2 class="has-child" :class="{'isOpen':isOpen}" @click="isOpen=!isOpen">{{title}}</h2>
<menu-component v-show="isOpen" v-for="c in child" :title=c.name :child="c.childNodes" :url="c.url">
</menu-component>
</template>
<a :href="url" v-else>{{title}}</a>
</li>
</ul>
`
})
app.mount('#app');
父子元件之間的溝通方式有個流傳已久的口訣:「Props in, Event out」。—重新認識 Vue.js
當子元件要將處理過的資料送回外層父元件時,可以透過this.$emit
觸發@update="updateInfo"
來更新外層資料,用下圖可以清楚的知道資料的流動。
deep
watch
裡面的參數。我們都知道對象 {} 都指向一個內存地址。當其屬性改變的時候,對象的內存地址沒發生改變。故當watch
監聽一個對象的時候,對象屬性發生改變,watch
監聽不到。為了發現對象內部值的變化,可以在選項參數中指定deep: true
。——Vue.js中的methods,computed,watch。
講到v-model
雙向綁定元件前要先回顧一下之前的表單綁定,先前在綁定input
時會使用v-bind
,可以將其拆解為下
<input v-model="msg">
<!-- 拆解 -->
<input v-bind:value="msg" v-on:input="msg=$event.target.value">
使用在元件雙向綁定也是類似的概念,component
接收一個 modelValue
的值,然後透過觸發 update:modelValue
事件來更新值。
<my-component v-model="msg"></my-component>
const app = Vue.createApp({
data() {
return {
msg: 'Hello Vue!!'
}
}
});
app.component('my-component', {
props: ['modelValue'],
template: `
<input type="text" :modelValue="modelValue" @input="$emit('update:modelValue',$event.target.value)">
`
})
自定義事件上使用v-model,屬性及事件的名稱改為
prop
:value ⇒ modelValueevent
:input ⇒ update:modelValue當父層元件要傳遞給最底部的元件時,可以透過provide
和inject
機制。
<input type="text" v-model="msg">
<list-component></list-component>
const app = Vue.createApp({
data() {
return {
msg: 'Hello Vue!!'
}
},
provide() {
return {
provideMsg: this.msg,
provideMsg2: Vue.computed(() => this.msg)
}
}
});
若要子層inject
取回的資料與上層連動,需透過Vue.computed()
包裝,包裝後的物件要加.value
才可以運作。
app.component('list-component', {
template: `
<ul>
<li v-for="i in 3">
{{i}}
<list-item></list-item>
</li>
</ul>
`,
components: {
'list-item': {
inject: ['provideMsg', 'provideMsg2'],
template: `
<div>{{provideMsg}}</div>
<div>{{provideMsg2.value}}</div>`
}
}
})
底層互相傳遞資料可以透過mitt
處理。
mitt()
實體指定一個變數bus
,並在vue實體上建立created
,在bus
身上註冊reset
事件<button-counter>
元件身上新增created
以對應reset
事件<reset-button>
元件身上放上reset
方法Vue.js 3.x已不建議使用上述方式,改為Vuex管理
後面某一章節有這部分的內容,等到那天在來深入研究這一部分!今日的篇幅真夠長的?
JavaScript - 原始型別概述
https://ithelp.ithome.com.tw/articles/10192598
data為Object或Array時的淺拷貝特性
https://yuugou727.github.io/blog/2017/07/23/vue-data-is-object-or-array/
Vue.js中的methods,computed,watch。
https://codertw.com/程式語言/695853/#outline__3
Vue 3 到底有什么不同:v-model 升级了
https://segmentfault.com/a/1190000023462922